import webapp2
import jinja2
import os
import logging
import settings
import urllib2

from google.appengine.ext import db
from google.appengine.api import users
from decorators import login_required, admin_user
from model import Registration, LocationStats, Item, Temp_User
from google.appengine.api import mail

jinja_environment = jinja2.Environment(
    loader=jinja2.FileSystemLoader(os.path.dirname(__file__)), extensions=["jinja2.ext.do", "jinja2.ext.autoescape"])

def register_filter(func):
    '''
    Quick decorator to add a template filter method.
    :param func:
    :return:
    '''
    jinja_environment.filters[func.__name__] = func
    return func

@register_filter
def key(value):
    '''
    Special encoder for registration items to produce their keys
    '''
    return value.key()
    
def registration_book_key(registration_book_name=None):
    """Constructs a Datastore key for a Registration_Book entity with registration_book_name."""
    return db.Key.from_path('Registration_Book', registration_book_name or 'default_registration_book')

class Stats(webapp2.RequestHandler):
    @login_required
    def get(self):
        regs = Registration.all()
        count = regs.count()
        locs = LocationStats.all()
        
        email_list = ""
        for reg in regs:
            email_list += reg.email + "; "
        
        template = jinja_environment.get_template('templates/stats.html')
        self.response.out.write(template.render(count=count, locs=locs, regs=regs, emails=email_list))

class PayPal(webapp2.RequestHandler):
    def get(self):
        #self.redirect("http://www.google.com")
        template = jinja_environment.get_template('templates/paypal.html')
        self.response.out.write(template.render())
        
class FrontPage(webapp2.RequestHandler):
    def get(self):
        #self.redirect("http://www.google.com")
        url = users.create_logout_url("/")
        template = jinja_environment.get_template('templates/front_page.html')
        self.response.out.write(template.render(url=url))

class EnterRegistration(webapp2.RequestHandler):
    def get(self):
        template = jinja_environment.get_template('templates/enter_registration.html')
        self.response.out.write(template.render())
    
    def post(self):
        self.response

class AdminPage(webapp2.RequestHandler):
    @login_required
    def get(self):
        # Ancestor Queries, as shown here, are strongly consistent with the High
        # Replication Datastore. Queries that span entity groups are eventually
        # consistent. If we omitted the ancestor from this query there would be a
        # slight chance that registration that had just been written would not show up
        # in a query.
        registrations = db.GqlQuery("SELECT * "
                                "FROM Registration "
                                "WHERE ANCESTOR IS :1 "
                                "ORDER BY date DESC",
                                registration_book_key())

        logout_url = users.CreateLogoutURL("/")
        template = jinja_environment.get_template('templates/admin.html')
        self.response.out.write(template.render(registrations=registrations, logout_url=logout_url))

class Temp_User_Info(webapp2.RequestHandler):
    def post(self):
        # We set the same parent key on the 'Registration' to ensure each registration is in
        # the same entity group. Queries across the single entity group will be
        # consistent. However, the write rate to a single entity group should
        # be limited to ~1/second.
        # registration_book_name = self.request.get('registration_book_name')
        # registration = Registration(parent=registration_book_key(registration_book_name))
        temp_user = Temp_User()
        
        if users.get_current_user():
            temp_user.author = users.get_current_user().nickname()
        
        city = self.request.get('city')
        state = self.request.get('state')
        email = self.request.get('email')
        temp_user.first_name = self.request.get('first_name')
        temp_user.last_name = self.request.get('last_name')
        temp_user.street_address = self.request.get('street_address')
        temp_user.city = city
        temp_user.state = state
        temp_user.email = email
        temp_user.zip_code = self.request.get('zip_code')
        temp_user.phone_number = self.request.get('phone_number')
        temp_user.date_entered = self.request.get('date_entered')
        
        LocationStats().add_loc(city, state)
        
        temp_user.put()
        
        #Get Express Checkout Token
        key = temp_user.key()
        logging.info("KEY: %s" % key)
        data = ('''%s
        &METHOD=SetExpressCheckout
        &VERSION=94
        &PAYMENTREQUEST_0_PAYMENTACTION=Sale
        &PAYMENTREQUEST_0_AMT=15.00
        &PAYMENTREQUEST_0_ITEMAMT=15.00
        &PAYMENTREQUEST_0_SHIPPINGAMT=0.00
        &PAYMENTREQUEST_0_HANDLINGAMT=0.00
        &PAYMENTREQUEST_0_TAXAMT=0.00
        &PAYMENTREQUEST_0_INSURANCEAMT=0.00
        &PAYMENTREQUEST_0_INSURANCEOPTIONOFFERED=false
        &PAYMENTREQUEST_0_DESC=Registration for the OYPAA 2013 Convention
        &PAYMENTREQUEST_0_CURRENCYCODE=USD
        &L_PAYMENTREQUEST_0_NAME0=Registration
        &L_PAYMENTREQUEST_0_DESC0=OYPAA 2013 Registration
        &L_PAYMENTREQUEST_0_AMT0=15.00
        &L_PAYMENTREQUEST_0_QTY0=1
        &REQCONFIRMSHIPPING=0
        &NOSHIPPING=1
        &EMAIL=%s
        &BRANDNAME=OYPAA 2013
        &cancelUrl=%s/cancel
        &returnUrl=%s/review_payment?key=%s''' % (settings.PAYPAL_AUTH, 
                                                  email, 
                                                  settings.HOST,
                                                  settings.HOST,
                                                  key))
        logging.info("data:%s" % data)
        data = data.replace('\n', '').replace('        ', '')
        req = urllib2.Request(settings.PAYPAL_SERVER, data)
        response = urllib2.urlopen(req)
        return_data = response.read().split('&')
        return_data_dict = {}
        for d in return_data:
            item = d.split('=')
            return_data_dict[item[0]] = item[-1]
        logging.info("Return Data: %s" % return_data_dict)
        token = return_data_dict['TOKEN']
        template = jinja_environment.get_template('templates/paypal.html')
        self.response.out.write(template.render(settings=settings, 
                                                user=temp_user, 
                                                token=token,
                                                return_data=return_data_dict))

class ReviewHandler(webapp2.RequestHandler):
    def get(self):
        success_data = {}
        for item in self.request.GET.items():
            k,v = item
            success_data[k] = v
        key = success_data['key']
        token = success_data['token']
        payer_id = success_data['PayerID']
        data = ('''%s
        &METHOD=GetExpressCheckoutDetails
        &VERSION=94
        &TOKEN=%s''' % (settings.PAYPAL_AUTH, token))
        data = data.replace('\n', '').replace('        ', '')
        req = urllib2.Request(settings.PAYPAL_SERVER, data)
        response = urllib2.urlopen(req)
        return_data = response.read().split('&')
        return_data_dict = {}
        for d in return_data:
            item = d.split('=')
            return_data_dict[item[0]] = item[-1]
        logging.info("Return Data: %s" % return_data_dict)
        temp_user = db.get(key)
        template = jinja_environment.get_template('templates/review_payment.html')
        email = urllib2.unquote(return_data_dict['EMAIL'])
        #desc = urllib2.unquote(return_data_dict['DESC'])
        #amt = urllib2.unquote(return_data_dict['AMT'])
        taxamt = urllib2.unquote(return_data_dict['TAXAMT'])
        quantity = return_data_dict['L_PAYMENTREQUEST_0_QTY0']
        desc = urllib2.unquote(return_data_dict['L_PAYMENTREQUEST_0_DESC0'])
        amt = urllib2.unquote(return_data_dict['L_AMT0'])
        self.response.out.write(template.render(settings=settings, 
                                                token=token,
                                                payer_id=payer_id,
                                                key=key,
                                                email=email,
                                                desc=desc,
                                                amt=amt,
                                                taxamt=taxamt,
                                                quantity=quantity,
                                                user=temp_user,
                                                user_data=return_data_dict))
        
class PayHandler(webapp2.RequestHandler):
    def get(self):
        # Confirm ORDER AUTHORIZATION
        success_data = {}
        for item in self.request.GET.items():
            k,v = item
            success_data[k] = v
        key = success_data['key']
        token = success_data['token']
        payer_id = success_data['PayerID']
        data = ('''%s
        &METHOD=DoExpressCheckoutPayment
        &VERSION=94
        &TOKEN=%s
        &PAYERID=%s
        &PAYMENTREQUEST_0_PAYMENTACTION=Sale
        &PAYMENTREQUEST_0_AMT=15.00
        &PAYMENTREQUEST_0_CURRENCYCODE=USD''' % (settings.PAYPAL_AUTH, token, payer_id))
        data = data.replace('\n', '').replace('        ', '')
        req = urllib2.Request(settings.PAYPAL_SERVER, data)
        response = urllib2.urlopen(req)
        return_data = response.read().split('&')
        return_data_dict = {}
        for d in return_data:
            item = d.split('=')
            return_data_dict[item[0]] = item[-1]
            logging.info("Item: %s" % item)
        logging.info("Return Data: %s" % return_data_dict)
        
        # DO CAPTURE
        # Capture Future Payment
        authorization_id = return_data_dict['PAYMENTINFO_0_TRANSACTIONID']
        logging.info("TransactionID: %s" % authorization_id)
        token = payer_id = return_data_dict['TOKEN']
        
        '''
        data = (%s
        &METHOD=DoCapture
        &VERSION=94
        &AUTHORIZATIONID=%s
        &AMT=15.00
        &CURRENCYCODE=USD
        &COMPLETETYPE=Complete % (settings.PAYPAL_AUTH, authorization_id))
        data = data.replace('\n', '').replace('        ', '')
        req = urllib2.Request(settings.PAYPAL_SERVER, data)
        response = urllib2.urlopen(req)
        return_data = response.read().split('&')
        return_data_dict = {}
        for d in return_data:
            item = d.split('=')
            return_data_dict[item[0]] = item[-1]
            logging.info("Item: %s" % item)
        logging.info("Return Data: %s" % return_data_dict)
        '''
        temp_user = Temp_User.get(key)
        
        registration = Registration(parent=registration_book_key())
        test_reg = Registration.all().filter("temp_user_key ==", key).get()
        if test_reg == None: 
            
            registration = Registration(parent=registration_book_key())
            
            if users.get_current_user():
                registration.author = users.get_current_user().nickname()
            
            city = temp_user.city
            state = temp_user.state
            registration.first_name = temp_user.first_name
            registration.last_name = temp_user.last_name
            registration.street_address = temp_user.street_address
            registration.city = city
            registration.state = state
            registration.email = temp_user.email
            registration.zip_code = temp_user.zip_code
            registration.phone_number = temp_user.phone_number
            registration.temp_user_key = key
            #registration.date_entered = temp_user.date_entered
            
            LocationStats().add_loc(city, state)
            
            registration.put()
        else:
            registration=test_reg
        
        timestamp = urllib2.unquote(return_data_dict['TIMESTAMP'])
        trans_id = urllib2.unquote(return_data_dict['PAYMENTINFO_0_TRANSACTIONID'])
        payment_type = urllib2.unquote(return_data_dict['PAYMENTINFO_0_PAYMENTTYPE'])
        payment_time = urllib2.unquote(return_data_dict['PAYMENTINFO_0_ORDERTIME'])
        payment_amt = urllib2.unquote(return_data_dict['PAYMENTINFO_0_AMT'])
        
        try:
            mail.send_mail(sender="NO-REPLY OYPAA 2013 Registration Confirmation Email <no-reply@oypaa-registration.appspotmail.com>",
                  to="%s %s <%s>"  % (temp_user.first_name, temp_user.last_name, temp_user.email),
                  subject="Your OYPAA 2013 Registration Confirmation",
                  body="""
                Dear %s:
                
                Congratulations! You have successfully Registered for OYPAA 2013. Please save this email for your records.
                
                User Confirmation
                First Name: %s
                Last Name: %s
                Address: %s
                City: %s
                State: %s
                Zip: %s
                Email: %s
                Phone Number: %s
                Registration ID: %s
                
                Payment Confirmation
                Timestamp: %s
                Transaction ID: %s
                Payment Type: %s
                Payment Order Time: %s 
                Payment Amount: %s
                
                Thank you,
                
                OYPAA 2013
                
                """ % (registration.first_name, 
                       registration.first_name, 
                       registration.last_name, 
                       registration.street_address,
                       registration.city,
                       registration.state,
                       registration.zip_code,
                       registration.email,
                       registration.phone_number,
                       key,
                       timestamp,
                       trans_id,
                       payment_type,
                       payment_time,
                       payment_amt))
        except mail.Error, e:
            logging.warning("The email could not be sent: %s" % e)
            
        template = jinja_environment.get_template('templates/success.html')
        user_id=registration.key().id()
        self.response.out.write(template.render(settings=settings,
                                                timestamp=timestamp,
                                                trans_id=trans_id,
                                                payment_type=payment_type,
                                                payment_time=payment_time,
                                                payment_amt=payment_amt, 
                                                user=registration,
                                                user_id=user_id))        
        
        
class CancelHandler(webapp2.RequestHandler):
    def get(self):
        success_data = {}
        for item in self.request.GET.items():
            k,v = item
            success_data[k] = v
        data = "USER=store_1353300406_biz_api1.gmail.com&PWD=1353300449&SIGNATURE=ANLnaACloED7V40WcpjQrlVjs72NA8rQtCcrGoenjm0sBerMOkqJng4I&METHOD=GetExpressCheckoutDetails&VERSION=94&TOKEN=%s" % success_data['token']
        req = urllib2.Request(settings.PAYPAL_SERVER, data)
        response = urllib2.urlopen(req)
        return_data = response.read().split('&')
        return_data_dict = {}
        for d in return_data:
            item = d.split('=')
            return_data_dict[item[0]] = item[-1]
        logging.info("Return Data: %s" % return_data_dict)
        template = jinja_environment.get_template('templates/cancel.html')
        self.response.out.write(template.render(settings=settings)) 

class Registration_Book(webapp2.RequestHandler):
    
    def post(self):
        # We set the same parent key on the 'Registration' to ensure each registration is in
        # the same entity group. Queries across the single entity group will be
        # consistent. However, the write rate to a single entity group should
        # be limited to ~1/second.
        # registration_book_name = self.request.get('registration_book_name')
        # registration = Registration(parent=registration_book_key(registration_book_name))
        registration = Registration(parent=registration_book_key())
        
        if users.get_current_user():
            registration.author = users.get_current_user().nickname()
        
        city = self.request.get('city')
        state = self.request.get('state')
        registration.first_name = self.request.get('first_name')
        registration.last_name = self.request.get('last_name')
        registration.street_address = self.request.get('street_address')
        registration.city = city
        registration.state = state
        registration.email = self.request.get('email')
        registration.zip_code = self.request.get('zip_code')
        registration.phone_number = self.request.get('phone_number')
        registration.date_entered = self.request.get('date_entered')
        
        LocationStats().add_loc(city, state)
        
        registration.put()
        self.redirect('/admin')
        
class IPNHandler(webapp2.RequestHandler):
    def get(self):
        data = {}
        for item in self.request.GET.items():
            logging.info('IPN data: %s' % item)
            k,v = item
            data[k] = v

    def post(self):
        data = {}
        for item in self.request.GET.items():
            logging.info('IPN data: %s' % item)
            k,v = item
            data[k] = v
        
class ItemAdmin(webapp2.RequestHandler):
    def get(self):
        q = db.GqlQuery("SELECT * FROM Item ")
        items = q.run()
        template = jinja_environment.get_template('item.html')
        self.response.out.write(template.render(items=items))

    def post(self):
        user = users.get_current_user()
        if not user:
            self.redirect( users.create_login_url( "/sell" ) )
        else:
            item = Item()
            item.owner=user
            item.title=self.request.get("title")
            item.price=long(float(self.request.get("price")) * 100)
            item.put()

        self.redirect('/item')

class Delete_Registration(webapp2.RequestHandler):
    @login_required
    def get(self):
        # Create the handler's response "Hello World!" in plain text.
        # registration_book_name = self.request.get('registration_book_name')
        key = self.request.get('key')
        db.delete(key)
        self.redirect('/admin')

app = webapp2.WSGIApplication([('/', FrontPage),
                               ('/enter_registration', EnterRegistration),
                               ('/admin', AdminPage),
                               ('/item', ItemAdmin),
                               ('/paypal', PayPal),
                               ('/ipn', IPNHandler),
                               ('/sign', Registration_Book),
			                   ('/delete', Delete_Registration),
                               ('/stats', Stats),
                               ('/start_registration', Temp_User_Info),
                               ('/review_payment', ReviewHandler),
                               ('/pay_registration', PayHandler),
                               ('/cancel', CancelHandler)],
                              debug=True)
